import {hasOwn, isDef} from "../../../shared/util";
import {isRealNode, isSameNode} from "../../../core/vdom/utils";
import {VIRTUAL_NODE_TYPE} from "../../../constant";

/**
 * 组装 vnode 节点中的静态 class 属性与动态 class 属性
 * @param {VNode | HTMLElement} vnode
 * @param {HTMLElement} element
 * @return {Array<String>}
 */
function getClass (vnode) {
    const classList = [];

    if (isRealNode(vnode)) {
        vnode.classList.forEach(function (className) {
            classList.push(className);
        });
    }
    else {
        let staticClassStr = "";
        let bindClassObj = null;

        // 如果是根节点, 需要获取组件占位节点的静态 class 字符串
        if (vnode.context.vnode === vnode) {
            // 获取组件实例
            const context = vnode.context;
            // 查看组件属性中是否存在 style 属性
            if (hasOwn(context, 'class') && isDef(context.class)) {
                const componentVNodeClass = context.class;
                componentVNodeClass.split(/\s+/).forEach(function (className) {
                    if (className.trim().length !== 0) {
                        classList.push(className);
                    }
                });
            }
        }

        // fixme 先不实现组件动态 class 的绑定
        // todo 如果有时间,实现组件动态 class 的绑定

        // 获取静态 CSS class 字符串
        if (isDef(vnode.data.attrs.class))  {
            staticClassStr = vnode.data.attrs.class;
            // 处理静态字符串
            staticClassStr.split(/\s+/).forEach(function (className) {
                if (className.trim().length !== 0) {
                    classList.push(className);
                }
            });
            vnode.data.staticClass = vnode.data.attrs.class;
            delete vnode.data.attrs.class;
        }

        // 获取动态 CSS class 绑定对象
        if (isDef(vnode.data.bindAttrs) && isDef(vnode.data.bindAttrs.class)) {
            bindClassObj = vnode.data.bindAttrs.class;
            // 处理动态绑定字符串
            Object.keys(bindClassObj).forEach(function (className) {
                if (bindClassObj[className]) {
                    classList.push(className);
                }
            });
            vnode.data.bindClass = vnode.data.bindAttrs.class;
            delete vnode.data.bindAttrs.class;
        }
    }

    return classList;
}

/**
 *
 * @param {HTMLElement | VNode} oldNode
 * @param {VNode} newNode
 */
function updateClass (oldNode, newNode) {

    if (newNode.nodeType !== VIRTUAL_NODE_TYPE.ELEMENT) {
        return;
    }

    const oldClassList = getClass(oldNode);
    const newClassList = getClass(newNode);

    // 获取真实 DOM 节点
    let elem = null;
    isRealNode(oldNode)
        ? elem = oldNode
        : elem = newNode.elem;

    // 删除 newClassList 中没有的 class
    for (let i=0; i<oldClassList.length; i++) {
        const oldClassName = oldClassList[i];
        if (!newClassList.includes(oldClassName)) {
            elem.classList.remove(oldClassName);
        }
    }

    // 新增 oldClassList 中没有的 class
    for (let i=0; i<newClassList.length; i++) {
        const newClassName = newClassList[i];
        if (!oldClassList.includes(newClassName)) {
            elem.classList.add(newClassName);
        }
    }
}

export default {
    mount: updateClass,
    update: updateClass
};

